/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bbmangadownloader.gui.control;

import bbmangadownloader.bus.model.data.DownloadTask;
import bbmangadownloader.bus.model.data.DownloadTask.DownloadTaskStatus;
import bbmangadownloader.entity.Chapter;
import bbmangadownloader.gui.bus.TaskDownloader;
import bbmangadownloader.gui.model.ChapterDownloadModel;
import bbmangadownloader.manager.ConfigManager;
import bbmangadownloader.manager.HistoryManager;
import bbmangadownloader.manager.entity.History;
import bbmangadownloader.ult.GUIUtilities;
import bbmangadownloader.ult.MySwingUtilities;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
 * @author Bach
 */
public class PanelDownload extends javax.swing.JPanel implements
        TaskDownloader.ITaskDownloaderListener {

    private ChapterDownloadModel modelDownload;
    private final ArrayList<DownloadTask> queue = new ArrayList<DownloadTask>();

    private static int getMaxiumNumberDownload() {
        return ConfigManager.getCurrentInstance().getMaxiumDownloadInQueue();
    }

    /**
     * Creates new form PanelDownload
     */
    public PanelDownload() {
//        if (listener == null) {
//            throw new  ("IPanelDownloadListener must not be null");
//        }
//        this.listener = listener;
        initComponents();
//        tblDownload.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        initData();
        initHeader();
    }

    private void initData() {
        this.modelDownload = new ChapterDownloadModel();
        tblDownload.setModel(modelDownload);

        tblDownload.setComponentPopupMenu(popDownload);
        tblDownload.setInheritsPopupMenu(true);
    }

    private void initHeader() {
        //<editor-fold>
        tblDownload.getColumnModel().getColumn(0).setPreferredWidth(50);
        tblDownload.getColumnModel().getColumn(0).setMaxWidth(100);
        tblDownload.getColumnModel().getColumn(1).setPreferredWidth(200);
        tblDownload.getColumnModel().getColumn(2).setPreferredWidth(100);
        tblDownload.getColumnModel().getColumn(2).setMaxWidth(100);
        tblDownload.getColumnModel().getColumn(3).setPreferredWidth(150);
//        tblDownload.setAutoCreateColumnsFromModel(false);
        //</editor-fold>        
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        popDownload = new javax.swing.JPopupMenu();
        mnDownloadStartImmediately = new javax.swing.JMenuItem();
        mnDownloadStartQueue = new javax.swing.JMenuItem();
        mnDownloadResume = new javax.swing.JMenuItem();
        mnDownloadStop = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        mnDownloadRemove = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JPopupMenu.Separator();
        mnDownloadViewInBrowser = new javax.swing.JMenuItem();
        mnDownloadViewFolder = new javax.swing.JMenuItem();
        jScrollPane1 = new javax.swing.JScrollPane();
        tblDownload = new org.jdesktop.swingx.JXTable();

        popDownload.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
            public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
                popDownloadPopupMenuWillBecomeVisible(evt);
            }
            public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
            }
            public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
            }
        });

        mnDownloadStartImmediately.setText("Start (Immediately)");
        mnDownloadStartImmediately.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mnDownloadStartImmediatelyActionPerformed(evt);
            }
        });
        popDownload.add(mnDownloadStartImmediately);

        mnDownloadStartQueue.setText("Start (Queue)");
        mnDownloadStartQueue.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mnDownloadStartQueueActionPerformed(evt);
            }
        });
        popDownload.add(mnDownloadStartQueue);

        mnDownloadResume.setLabel("Resume");
        mnDownloadResume.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mnDownloadResumeActionPerformed(evt);
            }
        });
        popDownload.add(mnDownloadResume);

        mnDownloadStop.setLabel("Stop");
        mnDownloadStop.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mnDownloadStopActionPerformed(evt);
            }
        });
        popDownload.add(mnDownloadStop);
        popDownload.add(jSeparator1);

        mnDownloadRemove.setLabel("Remove");
        mnDownloadRemove.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mnDownloadRemoveActionPerformed(evt);
            }
        });
        popDownload.add(mnDownloadRemove);
        popDownload.add(jSeparator2);

        mnDownloadViewInBrowser.setText("View In Browser");
        mnDownloadViewInBrowser.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mnDownloadViewInBrowserActionPerformed(evt);
            }
        });
        popDownload.add(mnDownloadViewInBrowser);

        mnDownloadViewFolder.setText("Open Folder");
        mnDownloadViewFolder.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mnDownloadViewFolderActionPerformed(evt);
            }
        });
        popDownload.add(mnDownloadViewFolder);

        tblDownload.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null}
            },
            new String [] {
                "Title 1"
            }
        ));
        jScrollPane1.setViewportView(tblDownload);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGap(0, 0, 0)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 93, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void mnDownloadStartImmediatelyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnDownloadStartImmediatelyActionPerformed
        doDownloadStartDownload();
    }//GEN-LAST:event_mnDownloadStartImmediatelyActionPerformed

    private void mnDownloadRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnDownloadRemoveActionPerformed
        doDownloadRemoveFromDownload();
    }//GEN-LAST:event_mnDownloadRemoveActionPerformed

    private void mnDownloadViewInBrowserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnDownloadViewInBrowserActionPerformed
        doDownloadViewInBrowser();
    }//GEN-LAST:event_mnDownloadViewInBrowserActionPerformed

    private void mnDownloadViewFolderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnDownloadViewFolderActionPerformed
        doDownloadOpenDownloadFolder();
    }//GEN-LAST:event_mnDownloadViewFolderActionPerformed

    private void mnDownloadResumeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnDownloadResumeActionPerformed
        doDownloadResume();
    }//GEN-LAST:event_mnDownloadResumeActionPerformed

    private void mnDownloadStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnDownloadStopActionPerformed
        doDownloadStop();
    }//GEN-LAST:event_mnDownloadStopActionPerformed

    private void popDownloadPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_popDownloadPopupMenuWillBecomeVisible
        doEnableMenuItem();
    }//GEN-LAST:event_popDownloadPopupMenuWillBecomeVisible

    private void mnDownloadStartQueueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnDownloadStartQueueActionPerformed
        doStartQueue();
    }//GEN-LAST:event_mnDownloadStartQueueActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JPopupMenu.Separator jSeparator2;
    private javax.swing.JMenuItem mnDownloadRemove;
    private javax.swing.JMenuItem mnDownloadResume;
    private javax.swing.JMenuItem mnDownloadStartImmediately;
    private javax.swing.JMenuItem mnDownloadStartQueue;
    private javax.swing.JMenuItem mnDownloadStop;
    private javax.swing.JMenuItem mnDownloadViewFolder;
    private javax.swing.JMenuItem mnDownloadViewInBrowser;
    private javax.swing.JPopupMenu popDownload;
    private org.jdesktop.swingx.JXTable tblDownload;
    // End of variables declaration//GEN-END:variables

    private void doDownloadRemoveFromDownload() {
        int[] selectedRows = tblDownload.getSelectedRows();
        DownloadTask[] deletingTasks = new DownloadTask[selectedRows.length];
        Arrays.sort(selectedRows);
        for (int i = selectedRows.length - 1; i >= 0; i--) {
            deletingTasks[i] = (DownloadTask) tblDownload.getValueAt(selectedRows[i], -1);
        }

        for (DownloadTask task : deletingTasks) {
            if (task.getStatusEnum() == DownloadTaskStatus.Queue) {
                queue.remove(task);
            }
            task.getDownloader().remove();
            modelDownload.removeTask(task);
        }
        modelDownload.fireTableDataChanged();

    }

    private void doDownloadOpenDownloadFolder() {
        DownloadTask task = modelDownload.getTaskAt(tblDownload.getSelectedRow());
        DownloadTaskStatus s = task.getStatusEnum();
        if (s == DownloadTaskStatus.Done || s == DownloadTask.DownloadTaskStatus.Downloading) {
            GUIUtilities.openFile(task.getDownloadTo());
        }
    }

    private void doDownloadViewInBrowser() {
        DownloadTask task = MySwingUtilities.<DownloadTask>getSelectedObject(tblDownload);
        if (task != null && task.getChapter() != null) {
            GUIUtilities.openLink(task.getChapter().getUrl());
        }
    }

    private void doDownloadStop() {
        List<DownloadTask> lstTask = MySwingUtilities.<DownloadTask>getSelectedObjects(tblDownload);
        for (DownloadTask task : lstTask) {
            task.getDownloader().stop();
        }
    }

    private void doDownloadResume() {
        List<DownloadTask> lstTask = MySwingUtilities.<DownloadTask>getSelectedObjects(tblDownload);
        for (DownloadTask task : lstTask) {
            task.getDownloader().resume();
        }
    }

    private void doDownloadStartDownload() {
        List<DownloadTask> lstTask = MySwingUtilities.<DownloadTask>getSelectedObjects(tblDownload);
        for (DownloadTask task : lstTask) {
            task.getDownloader().start();
        }
    }

    public void addChapter(Chapter c) {
        DownloadTask t = modelDownload.addChapter(c);
        if (t.getDownloader() == null) {
            t.setDownloader(new TaskDownloader(this, t));
        }
    }

    public void listAll() {
        for (DownloadTask t : modelDownload.getListDownload()) {
            System.out.println(t.getChapter().getDisplayName() + "\t"
                    + t.getDisplayStatus() + "\t" + t.getStatusEnum());
        }
    }

    @Override
    public void updateRecord(DownloadTask task) {
        modelDownload.fireDownloadTaskStatusUpdated(task);
    }

    private void doEnableMenuItem() {
        List<DownloadTask> lstSelectedTask = MySwingUtilities.<DownloadTask>getSelectedObjects(tblDownload);
        boolean isEnableStartNow = false, isEnableStop = false, isEnableResume = false,
                isEnableStatQueue = false;
        for (DownloadTask task : lstSelectedTask) {
            TaskDownloader downloader = task.getDownloader();
            if (downloader.isQueue()) {
                isEnableStatQueue = true;
            }
            if (downloader.isResume()) {
                isEnableResume = true;
            }
            if (downloader.isStart()) {
                isEnableStartNow = true;
            }
            if (downloader.isStop()) {
                isEnableStop = true;
            }
        }
        mnDownloadStartImmediately.setEnabled(isEnableStartNow);
        mnDownloadStop.setEnabled(isEnableStop);
        mnDownloadResume.setEnabled(isEnableResume);
        mnDownloadStartQueue.setEnabled(isEnableStatQueue);
    }

    private void doStartQueue() {
        boolean isAdded = false;
        List<DownloadTask> listTask = MySwingUtilities.<DownloadTask>getSelectedObjects(tblDownload);
        for (DownloadTask task : listTask) {
            DownloadTaskStatus status = task.getStatusEnum();
            if (status == DownloadTaskStatus.No
                    || status == DownloadTaskStatus.Error) {
                task.setStatus(DownloadTaskStatus.Queue);
                modelDownload.fireDownloadTaskStatusUpdated(task);
                queue.add(task);
                isAdded = true;
            }
        }
        if (isAdded) {
            invokeQueue();
        }
    }

    boolean isInvokingQueue = false;

    private void invokeQueue() {
        synchronized (queue) {
            isInvokingQueue = true;
            while (modelDownload.isDownloadable(getMaxiumNumberDownload()) && !queue.isEmpty()) {
                DownloadTask task = queue.remove(0);
                if (task.getStatusEnum() == DownloadTaskStatus.Queue) {
                    task.getDownloader().start();
                }
            }
            isInvokingQueue = false;
        }
    }

    @Override
    public void onTaskDownloadFinish(DownloadTask task) {
        History h = new History(
                task.getChapter().getManga().getMangaName(),
                task.getChapter().getManga().getUrl(),
                task.getChapter().getDisplayName(),
                task.getChapter().getUrl()
        );

        HistoryManager.addHistory(h);
        if (!isInvokingQueue) {
            invokeQueue();
        }
    }

    public boolean isAllDownloadDone() {
        for (DownloadTask task : modelDownload.getListDownload()) {
            if (task.getStatusEnum() != DownloadTaskStatus.Done) {
                return false;
            }
        }
        return true;
    }
}
